#include "MirrorBoss.h"
#include "GameGUI.h"
#include "GameApp.h"
#include "RewardOrb.h"
#include "Sword.h"

//-------------------------------------------------------------------------------------
MirrorBoss::MirrorBoss(string enemyID) : Player(enemyID)
{
	removeType(OBJECT_PLAYER);
	addType(OBJECT_ENEMY);
	addType(OBJECT_MIRROR_BOSS);
}
//-------------------------------------------------------------------------------------
MirrorBoss::MirrorBoss(void) : Player("enemies/mirrorboss.xml")
{
	removeType(OBJECT_PLAYER);
	addType(OBJECT_ENEMY);
	addType(OBJECT_MIRROR_BOSS);
}
//-------------------------------------------------------------------------------------
MirrorBoss::~MirrorBoss(void)
{
}
//-------------------------------------------------------------------------------------
void MirrorBoss::update(const unsigned long elapsedTime)
{
	if (this->getResources(RES_HEALTH) > 50.f) updateAi(elapsedTime);
	else updateAiGun(elapsedTime);
	Player::update(elapsedTime);
}
//-------------------------------------------------------------------------------------
void MirrorBoss::die()
{
	if(gun) this->removeGun();
	if(sword) this->removeSword();
	if(shield) this->removeShield();
}
//-------------------------------------------------------------------------------------
void MirrorBoss::updateAi(const unsigned long elapsedTime)
{
	//equipment
	if(gun) 
	{
		this->mMoveState = MOVE_IDLE;
		this->removeGun();
	}
	if(!sword)
	{
		equipSword();
		sword->setTarget(OBJECT_PLAYER);
	}
	if(!shield)
		equipShield();
	//often used information about position and orientation
	PlayerPtr player(gpApp->mpGameLogic->getCharacter());
	btTransform playerTrans = player->getBody()->getWorldTransform();
	btTransform selfTrans = mpBody->getWorldTransform();
	btVector3 playerDist = getLocalVector(playerTrans.getOrigin());
	float dist = playerDist.length();
	
	if(dist >= 20.f)return;
	//orientation
	if(playerDist.x() <= 0.f)
	{
		lookLeft();
	} else
	{
		lookRight();
	}
	//movement
	if(dist >= 2.f)
	{
		if(mStates[MOVE_LEFT])
			moveLeft();
		else
			moveRight();
	}
	if(playerDist.y() > 0.5f && (mStates[MOVE_WALL_LEFT] || mStates[MOVE_WALL_RIGHT]) && (getLocalVelocity().y() <= 0.f || !mStates[MOVE_AIR]) && mJumpCooldown == 0.f)
	{
		jump();
		btVector3 vel = getLocalVelocity();
		vel.setX(0.f);
		setLocalVelocity(vel);
		mJumpCooldown = 0.1f;
	}
	//combat
	if(dist < 2.f)
	{
		if(player->getMoveState() == MOVE_ATTACK || player->getMoveState() == MOVE_ATTACK2 || player->getMoveState() == MOVE_ATTACK3)
			block();
		else
		{
			unblock();
			normalAttack();
		}

	}
	mJumpCooldown -= elapsedTime / 1000.f;
	if(mJumpCooldown < 0.f) mJumpCooldown = 0.f;
}
//-------------------------------------------------------------------------------------
void MirrorBoss::updateAiGun(const unsigned long elapsedTime)
{
	//equipment
	if(sword) 
	{
		this->mMoveState = MOVE_IDLE;
		this->removeSword();
	}
	if (!gun)
	{
		equipSword();
		gun->setTarget(OBJECT_PLAYER);
	}
	if (!shield)
		equipShield();
	//often used information about position and orientation
	PlayerPtr player(gpApp->mpGameLogic->getCharacter());
	btTransform playerTrans = player->getBody()->getWorldTransform();
	btTransform selfTrans = mpBody->getWorldTransform();
	btVector3 playerDist = getLocalVector(playerTrans.getOrigin());
	float dist = playerDist.length();
	
	if (dist >= 20.f) return;
	//orientation
	if (playerDist.x() <= 0.f)
	{
		lookLeft();
	} else
	{
		lookRight();
	}
	//movement
	if (dist >= 7.0f)
	{
		if(mStates[MOVE_LEFT])
			moveLeft();
		else
			moveRight();
	}
	if(playerDist.y() > 0.5f && (mStates[MOVE_WALL_LEFT] || mStates[MOVE_WALL_RIGHT]) && (getLocalVelocity().y() <= 0.f || !mStates[MOVE_AIR]) && mJumpCooldown == 0.f)
	{
		jump();
		btVector3 vel = getLocalVelocity();
		vel.setX(0.f);
		setLocalVelocity(vel);
		mJumpCooldown = 0.1f;
	}
	//combat
	if (dist < 2.f || dist > 10.f)
	{
		if (player->getMoveState() == MOVE_ATTACK || player->getMoveState() == MOVE_ATTACK2 || player->getMoveState() == MOVE_PREPARESHOOT)
			block();
		else
		{
			unblock();

			if (playerDist.x() > 0.f)
			{
				lookLeft();
			} else
			{
				lookRight();
			}

			if(mStates[MOVE_LEFT])
				moveLeft();
			else
				moveRight();
		}

	}
	else
	{
		if (mShootCooldown)
		{
			if (playerDist.x() > 0.f)
			{
				lookLeft();
			} else
			{
				lookRight();
			}

			if(mStates[MOVE_LEFT])
				moveLeft();
			else
				moveRight();
		}
		else prepareShoot();
	}

	mJumpCooldown -= elapsedTime / 1000.f;
	if(mJumpCooldown < 0.f) mJumpCooldown = 0.f;

	if (mShootCooldown < elapsedTime) mShootCooldown = 0;
	else mShootCooldown -= elapsedTime;
}
//-------------------------------------------------------------------------------------
void MirrorBoss::prepareShoot(void)
{
	if (!mStates[MOVE_AIR] && mStates[MOVE_INTERRUPTIBLE])
	{
		mStates[MOVE_INTERRUPTIBLE] = false;
		mMoveState = MOVE_PREPARESHOOT;

		float angle = getMouseAngle();
		if (angle > 2.65f) angle = 2.65f;
		else if (angle < 0.6) angle = 0.4;
		else angle -= 0.3;
		mShootPos = angle / 3.14f;

		mpAnimator->playAnimation(ANIM_FULL, Ogre::String("Shoot"), false, false, 1.0f, 0.0f, 0.1f);

		mpGunParticle = gpApp->mpGameLogic->createParticleSystem(Ogre::String("FillWeapon"), cvt(gun->getBody()->getWorldTransform().getOrigin()));

		mShootCooldown = 1000;
	}
}
const float MirrorBoss::getMouseAngle(void) const
{
	btTransform &trans = mpBody->getWorldTransform();
	btVector3 dir = gpApp->mpGameLogic->getCharacter()->getBody()->getWorldTransform().getOrigin() - trans.getOrigin();
	dir = trans.getBasis() * dir;
	dir.setZ(0.0f);
	btVector3 xAxis = trans.getBasis() * btVector3(1.0f, 0.0f, 0.0f);
	
	return dir.angle(xAxis);;
}
//-------------------------------------------------------------------------------------
void MirrorBoss::recieveDmg(const btVector3 &pos, const float dmg)
{
	if (mInvulnerable > 0.0f) return;

	if(mMoveState == MOVE_BLOCK || mMoveState == MOVE_ATTACK_SHIELD)
	{
		if(mStates[MOVE_LEFT] == (getLocalVector(pos).x() < 0.f))
		{
			if (mBlockTime) return;
			mBlockTime = 1000;
			return;
		}
	}

	//recieve full damage if unable to block
	if((this->getResources(RES_HEALTH) -dmg) <= 0.f) die();

	changeResources(RES_HEALTH, -dmg);
	mInvulnerable = 0.2f;
}
//-------------------------------------------------------------------------------------
void MirrorBoss::scalePower(const char power)
{
	switch (power)
	{
	case 0:
		break;
	case 1:
		mHealthCap *= 2.0f;
		mHealth = mHealthCap;
		mEnergyCap *= 2.0f;
		mEnergy = mEnergyCap;
		getStats()->setStat(STAT_DAMAGE, getStats()->getStat(STAT_DAMAGE) * 2.0f);
		break;
	case 2:
		mHealthCap *= 3.5f;
		mHealth = mHealthCap;
		mEnergyCap *= 3.0f;
		mEnergy = mEnergyCap;
		getStats()->setStat(STAT_DAMAGE, getStats()->getStat(STAT_DAMAGE) * 3.5f);
		break;
	default:
		break;
	}
}